/**
 **************************************************************************
 * @file     sim_uart_init.c
 * @version  v1.0.
 * @date     2023-10-28
 * @brief    icon program
 * 模拟串口初始化程序，使用定时器制作
 **************************************************************************
 *
 **************************************************************************
 */

#include "at32f421_board.h"

enum {
    UART_START = 0, // 起始位
    UART_DAT   = 1, // 数据位
    UART_END   = 2, // 结束位
};
// 发送
uint8_t TX_BUF   = 0; // 串口发送缓冲
uint8_t TX_BUSY  = 0; // 串口忙标志
uint8_t TX_FLAG  = 0; // 串口发送标志位
uint8_t TX_BIT   = 0; // 发送位
uint8_t tx_index = 0;
// 接收
uint8_t RX_BUF       = 0; // 串口接收数据
uint8_t RX_BIT       = 0; // 接收位
uint8_t RX_FLAG      = 0; // 串口接收标志位
uint8_t RX_OVER_FLAG = 0; // 串口接收完毕标志位

/**
 * @brief  sim_uart_init
 * @param  Val: baund 波特率
 * 使用3倍采样率
 * @retval none
 */
void sim_uart_init(uint32_t Val)
{
    // IO初始化
    gpio_init_type gpio_init_struct;
    /* enable the led clock */
    crm_periph_clock_enable(SIM_UART_TX_GPIO_CRM_CLK, TRUE);
    /* set default parameter */
    gpio_default_para_init(&gpio_init_struct);
    /* configure the TX gpio */
    gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
    gpio_init_struct.gpio_out_type       = GPIO_OUTPUT_PUSH_PULL;
    gpio_init_struct.gpio_mode           = GPIO_MODE_OUTPUT;
    gpio_init_struct.gpio_pins           = SIM_UART_TX_PIN;
    gpio_init_struct.gpio_pull           = GPIO_PULL_NONE;
    gpio_init(SIM_UART_TX_GPIO, &gpio_init_struct);

    /* set default parameter */
    gpio_default_para_init(&gpio_init_struct);
    /* configure the RX gpio */
    // gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
    // gpio_init_struct.gpio_out_type  = GPIO_OUTPUT_OPEN_DRAIN;
    gpio_init_struct.gpio_mode = GPIO_MODE_INPUT;
    gpio_init_struct.gpio_pins = SIM_UART_RX_PIN;
    gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
    gpio_init(SIM_UART_RX_GPIO, &gpio_init_struct);

    // gpio置位
    SIM_UART_TX_GPIO->scr = SIM_UART_TX_PIN;
    SIM_UART_RX_GPIO->scr = SIM_UART_RX_PIN;

    // 定时器17初始化115200的3倍
    //

    /* enable tmr17 clock */
    crm_periph_clock_enable(CRM_TMR17_PERIPH_CLOCK, TRUE);

    /* tmr1 configuration */
    /* time base configuration */
    /* systemclock/12000/10000 = 1hz */
    tmr_base_init(TMR17, 345, 0);  //115200
    //tmr_base_init(TMR17, 2082, 0);  //19200
    tmr_cnt_dir_set(TMR17, TMR_COUNT_UP);

    /* overflow interrupt enable */
    tmr_interrupt_enable(TMR17, TMR_OVF_INT, TRUE);

    /* tmr1 overflow interrupt nvic init */
    nvic_priority_group_config(NVIC_PRIORITY_GROUP_4);
    nvic_irq_enable(TMR17_GLOBAL_IRQn, 0, 0);

    /* enable tmr1 */
    tmr_counter_enable(TMR17, TRUE);
}

/**
 * @brief  get_sim_uart_stat
 * @param  reutn: TX_BUSY
 * 0 = 空闲，1=忙
 * @retval none
 */
uint8_t get_sim_uart_stat(void)
{
    return TX_BUSY;
}

/**
 * @brief  write_sim_uart_buf
 * @param  val: 串口数据
 * @retval none
 */
void write_sim_uart_buf(uint8_t Val)
{
    if (!TX_BUSY) {
        TX_BUF  = Val;
        TX_BUSY = 1;
        TX_FLAG = 1;
    }
}

void tmr17_irqhandle_callback(void)
{
    static int txCnt     = 3;
    static int rxCnt     = 0;
    static uint8_t rxdat = 0;
    // 处理接收
    if (RX_FLAG) {
        if (--rxCnt == 0) {
            rxCnt = 3; // reset send baudrate counter
            if (--RX_BIT == 0) {
                RX_BUF = rxdat;                 // save the data to RBUF
                // if (0 == get_sim_uart_stat()) { // AA 55 01 02 03
                //     write_sim_uart_buf(RX_BUF);
                // }
                uart_rx_irq_del(RX_BUF);

                RX_FLAG      = 0; // stop receive
                RX_OVER_FLAG = 1; // set receive completed flag
            } else {
                rxdat >>= 1;
                if (gpio_input_data_bit_read(SIM_UART_RX_GPIO, SIM_UART_RX_PIN)) {
                    rxdat |= 0x80; // shift RX data to RX buffer
                }
            }
        }
    } else if (!gpio_input_data_bit_read(SIM_UART_RX_GPIO, SIM_UART_RX_PIN)) {
        rxdat        = 0;
        RX_FLAG      = 1; // set start receive flag
        rxCnt        = 4; // initial receive baudrate counter
        RX_BIT       = 9; // initial receive bit number (8 data bits + 1 stop bit)
        RX_OVER_FLAG = 0;
    }
    // 处理发送
    if (--txCnt == 0) {
        txCnt = 3;
        if (TX_FLAG) {

            switch (tx_index) {
                case UART_START:
                    SIM_UART_TX_GPIO->clr = SIM_UART_TX_PIN;
                    TX_BUSY               = 1;
                    TX_BIT                = 8;
                    tx_index              = UART_DAT;
                    break;
                case UART_DAT:
                    if (TX_BUF & 0x01)
                        SIM_UART_TX_GPIO->scr = SIM_UART_TX_PIN;
                    else
                        SIM_UART_TX_GPIO->clr = SIM_UART_TX_PIN;
                    TX_BUF >>= 1;
                    if (--TX_BIT == 0) {
                        tx_index = UART_END;
                    }
                    break;
                case UART_END:
                    SIM_UART_TX_GPIO->scr = SIM_UART_TX_PIN;
                    TX_FLAG               = 0;
                    TX_BUSY               = 0;
                    TX_BUF                = 0;
                    tx_index              = UART_START;

                    uart_tx_irq_del(TX_BUSY);

                    break;
                default:
                    tx_index = UART_START;
                    break;
            }
        }
    }
}
